/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author kpatel
 */
//import java.lang.reflect.InvocationTargetException;
import javax.swing.JOptionPane;
//import java.io.*;
//import java.util.*;



/*This is class file for the Instruction Set Simulator for SIMD approach.
 * This class defines main instructions each CFU can perform*/

/*The following instructions are used in this architecture. There is a method
 * for each instruction which takes some arguments and returns output; These
 * will be mostly registyers.
 *
 * 1- ADD - Addition of two 16 bits data
 * 2- MAC - Multiply and accumulation (MAC) in single cycle; We have only used
 * 			MAC unit instead of multiply unit to
 * 3- SLL - Shift Left Logical
 * 4- SRL - Shift Right Logical
 * 5- NOP - No Operation
 * 6- ADM - Addition and multiplication (ADM) in single cycle, not that the order
 * 			of operation is reverse than MAC instruction.
 * */



public class Cfu {

	/*Registers; There are four 16 bits registers in each CFU
	 * Two register to hold the input data to process
	 * Two registers to hold the output data because size of the
	 * output data may be larger than the input data
	 *
	 * */

	 // Global Variables

	public int[] register_array =  new int[4];
	//public static int = output_register_index;
	//static int out_reg_index;
	//register_array[0]=7;
	public int instr,
	in_reg1_index,  in_reg2_index,
	in_reg3_index,
	out_reg_index,
	shift_offset;

	//Constructor of CFU class. It takes values from the class fir_1 and initialize the CFU

/*	public Cfu (int instru,int reg1,int reg2, int reg3, int reg4, int offset)
	{

		instr = instru;
		in_reg1_index = reg1;
		in_reg2_index = reg2;
		in_reg3_index = reg3;
		out_reg_index = reg4;
		shift_offset = offset;
		register_array[0]=7;
		register_array[1]=9;
		register_array[2]=11;
	}*/
	public  void  Cfu_initialize (int instru,int reg1,int reg2, int reg3, int reg4, int offset)
	{

		instr = instru;
		in_reg1_index = reg1;
		in_reg2_index = reg2;
		in_reg3_index = reg3;
		out_reg_index = reg4;
		shift_offset = offset;
		//register_array[0]=7;
		//register_array[1]=9;
		//register_array[2]=11;
	}

	public void update_register(int register_index,int new_value)
	{
		//put one counter here to calculate number of register accesses
		register_array [register_index] = new_value;
	}

	public  void clear_register(int register_index)

	{
		register_array[register_index] = 0;
	}

	public  void copy_register(int source_register_index, int destination_registor_index)
	{

	}

	//Method of Addition operation
	public void add(int in_reg_index_1,int in_reg_index_2,int out_reg_index)
	{

		register_array[out_reg_index] = register_array[in_reg_index_1] + register_array[in_reg_index_2];

	}

	//Method of SLL (Shift Left Logical) operation
	public void sll(int in_reg_index,int shift_offset,int out_reg_index)
	{

		register_array[out_reg_index] = register_array[in_reg_index] << shift_offset;

	}

	//Method of SRL (Shift Right Logical) operation
	public  void srl(int in_reg_index,int shift_offset,int out_reg_index)
	{

		register_array[out_reg_index] = register_array[in_reg_index] >> shift_offset;

	}

	//Method of MAC (Multiply Accumulate) operation
	public void mac(int in_reg_index_1,int in_reg_index_2,int in_reg_index_3,int out_reg_index)
	{

		register_array[out_reg_index] =
			(register_array[in_reg_index_1] * register_array[in_reg_index_2])+register_array[in_reg_index_3];

	}

	//Method of ADM (Addition Multiply) operation
	public void adm(int in_reg_index_1,int in_reg_index_2,int in_reg_index_3,int out_reg_index)
	{

		register_array[out_reg_index] =
			(register_array[in_reg_index_1] + register_array[in_reg_index_2]) * register_array[in_reg_index_3];

	}


	/*Input arguments to this class will be in the following order
	 * 0- Instruction
	 * 1- 1st input register index
	 * 2- 2nd input register index; pass null if not required
	 * 3- 3rd input register index; pass null if not required
	 * 4- Output register index
	 * 5- Shift offset
	*/


	public int start_CFU()
	{

		//int instr = Integer.parseInt(args[0]);
		//int in_reg1_index = Integer.parseInt(args[1]);
		//int in_reg2_index = Integer.parseInt(args[2]);
		//int in_reg3_index = Integer.parseInt(args[3]);
		//out_reg_index = Integer.parseInt(args[4]);
		//int shift_offset = Integer.parseInt(args[5]);

		/*Instruction Decoding Logic for CFU*/

		switch (instr)
		{

		// This is NOP operation
		case 0:
			System.out.println("You have chosen NOP instruction and CFU will be idle");

			break;

		//This is Addition operation
		case 1:

			/* Argument order - input register 1 index,
			 * input register 2 index,
			 * output register index
			 * */
			add(in_reg1_index,in_reg2_index,out_reg_index);
			System.out.println("You have chosen ADD instruction");
			break;

		//This is Shift Left logical operation
		case 2:
			sll(in_reg1_index,shift_offset,out_reg_index);

			break;

		//This is Shift right logical operation
		case 3:
			srl(in_reg1_index,shift_offset,out_reg_index);
			break;

		//This is MAC operation
		case 4:
			mac(in_reg1_index, in_reg2_index, in_reg3_index, out_reg_index);

			break;

		//This is ADM (Addition and multiplication) operation
		case 5:
			adm(in_reg1_index, in_reg2_index, in_reg3_index, out_reg_index);
			break;

		default: JOptionPane.showMessageDialog(null, "The operation to CFU is not valid");


		}
		//JOptionPane.showMessageDialog(null, "The final answer from CFU is "+ register_array[out_reg_index] );
		System.out.println("Your final answer from CFU is "+ register_array[out_reg_index]);
		return (register_array[out_reg_index]);
	}
 }
